package com.ktjy.ktmall.servlet;

import cn.hutool.core.util.CharUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ktjy.ktmall.dao.BaseDao;
import com.ktjy.ktmall.entity.AjaxResult;
import com.ktjy.ktmall.entity.Order;
import com.ktjy.ktmall.entity.WxUser;
import com.ktjy.ktmall.service.OrderService;
import com.ktjy.ktmall.service.WxUserService;
import com.ktjy.ktmall.service.impl.OrderServiceImpl;
import com.ktjy.ktmall.service.impl.WxUserServiceImpl;
import com.ktjy.ktmall.util.*;
import com.mysql.cj.util.StringUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;

// 用于处理微信支付的请求
@WebServlet(name = "PayServlet", urlPatterns = "/uni/pay")
public class PayServlet extends HttpServlet {

    private String webAccessTokenhttps = null;
    private String appId = null;   //小程序ID(appId)
    private String secret = null; // 小程序密钥
    private String mchId = null;  // 商户号
    private String mchKey = null;
    private String tradeType = null; //支付类型
    private String notifyUrl = null; //支付回调地址
    private String uniformorder = null;
    private String orderquery = null; //订单的查询接口

    // 微信支付的相关配置参数
    public void getConfigParam() {
        Properties params = new Properties();
        String configFile = "wxpay.properties";//配置文件路径
        //加载配置文件到输入流中
        InputStream is= BaseDao.class.getClassLoader().getResourceAsStream(configFile);

        try {
            //从输入流中读取属性列表
            params.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //根据指定的获取对应的值
        appId = params.getProperty("wx.appId");
        secret = params.getProperty("wx.secret");
        webAccessTokenhttps = params.getProperty("wx.webAccessTokenhttps");
        mchId = params.getProperty("wx.mchId");
        mchKey = params.getProperty("wx.mchKey");
        tradeType = params.getProperty("wx.tradeType");
        notifyUrl = params.getProperty("wx.notifyUrl");
        uniformorder = params.getProperty("wx.uniformorder");
        orderquery = params.getProperty("wx.orderquery");
    }

    private WxUserService userService = null;
    private OrderService orderService = null;

    @Override
    public void init() throws ServletException {
        getConfigParam(); // 得到微信支付的相关配置参数
        userService = new WxUserServiceImpl();
        orderService = new OrderServiceImpl();
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String opr = request.getParameter("opr");
        PrintWriter out = response.getWriter();
        Object resp = null;
        if ("prepay".equals(opr)) {
            // 接收从小程序发送过来的请求参数
            Integer userId = Integer.valueOf(request.getParameter("userId"));
            // 得到从小程序响应过来的订单id
            Integer orderId = Integer.valueOf(request.getParameter("orderId"));
            //通过用户ID获取登录用户的详情信息
            WxUser loginUser = userService.findById(userId);
            // 通过订单id查询订单的详情信息
            Order orderInfo = orderService.findById(orderId);

            if (null == orderInfo) {
                resp = AjaxResult.error("订单已取消");
                out.print(JSON.toJSONString(resp));
                return;
            }

            if (orderInfo.getOrderState() != 1) {
                resp = AjaxResult.error("订单已支付，请不要重复操作");
                out.print(JSON.toJSONString(resp));
                return;
            }

            String nonceStr = CharUtils.getRandomString(32);
            //https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_7&index=3
            Map<String, String> resultObj = new TreeMap<String, String>();

            try {
                Map<String, String> parame = new TreeMap<String, String>();
                parame.put("appid", appId);
                // 商家账号。
                parame.put("mch_id", mchId);
                String randomStr = CharUtils.getRandomString(18).toUpperCase();
                // 随机字符串
                parame.put("nonce_str", randomStr);
                // 商户订单编号 (流水号)
                parame.put("out_trade_no", orderInfo.getOrderSn());
                Map orderGoodsParam = new HashMap();
                orderGoodsParam.put("order_id", orderInfo.getId());
                // 商品描述
                parame.put("body", "支付");

                //支付金额
                // 微信支付提交的金额是不能带小数点的，且是以分为单位，如果是以元为单位要处理下金额，即先乘以100，再去小数点
                parame.put("total_fee", String.valueOf(orderInfo.getActualPrice().multiply(new BigDecimal(100)).setScale(0,BigDecimal.ROUND_HALF_UP)));
                // 回调地址
                parame.put("notify_url", notifyUrl);
                // 交易类型APP
                parame.put("trade_type", tradeType);
                parame.put("spbill_create_ip", getClientIp(request));
                // 开发者id
                parame.put("openid", loginUser.getOpenId());

                String sign = WXPayUtil.generateSignature(parame, mchKey);
                // 数字签证
                parame.put("sign", sign);
                //将map集合转换成XML
                String xml = WXPayUtil.mapToXml(parame);
                Map<String, Object> resultUn = XmlUtil.xmlStrToMap(WechatUtil.requestOnce(uniformorder, xml));
                // 响应报文
                String return_code = MapUtils.getString("return_code", resultUn);
                String return_msg = MapUtils.getString("return_msg", resultUn);
                //
                if (return_code.equalsIgnoreCase("FAIL")) {
                    resp = AjaxResult.error("支付失败,失败信息是：" + return_msg);
                    out.print(JSON.toJSONString(resp));
                    return;
                } else if (return_code.equalsIgnoreCase("SUCCESS")) {
                    // 返回数据
                    String result_code = MapUtils.getString("result_code", resultUn);
                    String err_code_des = MapUtils.getString("err_code_des", resultUn);
                    if (result_code.equalsIgnoreCase("FAIL")) {
                        resp = AjaxResult.error("支付失败," + err_code_des);
                    } else if (result_code.equalsIgnoreCase("SUCCESS")) {
                        String prepay_id = MapUtils.getString("prepay_id", resultUn);
                        // 先生成paySign 参考https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_7&index=5
                        resultObj.put("appId", appId);
                        resultObj.put("timeStamp", DateUtils.timeToStr(System.currentTimeMillis() / 1000, DateUtils.DATE_TIME_PATTERN));
                        resultObj.put("nonceStr", nonceStr);
                        resultObj.put("package", "prepay_id=" + prepay_id);
                        resultObj.put("signType", "MD5");

                        //String paySign = WechatUtil.arraySign(resultObj, ResourceUtil.getConfigByName("wx.paySignKey"));
                        String packageSign = WXPayUtil.generateSignature(resultObj, mchKey);
                        resultObj.put("paySign", packageSign);
                        System.out.println("=============================支付签名paySign为：" + packageSign);
                        // 业务处理
                        // orderInfo.setPayId(prepay_id);
                        // 付款中
                        orderInfo.setOrderState(2);  // 2代表待发货
                        orderService.updatePayStatus(orderInfo); // 只需要修改订单状态为付款中即可
                        resp = AjaxResult.success("微信统一订单下单成功", resultObj);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                resp = AjaxResult.error("下单失败,error=" + e.getMessage());
            }
            out.print(JSON.toJSONString(resp));
        }
        out.flush();
        out.close();
    }

    /**
     * 获取请求方IP
     * @return 客户端Ip
     */
    public String getClientIp(HttpServletRequest request) {
        String xff = request.getHeader("X-Real-IP");
        if(xff!=null) {
            return xff;
        }
        xff = request.getHeader("x-forwarded-for");
        if (xff == null) {
            return "8.8.8.8";
        }
        return xff;
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}
